package com.winit.project.task;

import com.alibaba.fastjson.JSONObject;
import com.winit.core.task.Task;
import com.winit.core.task.TaskContainer;
import com.winit.project.core.branch.Project;
import com.winit.project.core.branch.ProjectConfig;
import com.winit.project.handler.BuildHandler;
import com.winit.project.handler.impl.BuildHandlerImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.concurrent.Callable;

/**
 * Created by wangjian on 16/9/8.
 */
public class BuildTask implements Callable{

    private static final Logger logger = LoggerFactory.getLogger(BuildTask.class);

    private Project project;
    private String vmLog;
    private String projectName;
    //发布任务线程 用于构建成功后直接发布的情况
    private Task releaseTask = null;

    private BuildHandler handler = new BuildHandlerImpl();

    public BuildTask(Project project,String vmLog) throws Exception {
        this.project = project;
        this.vmLog = vmLog;
        this.projectName = project.getFullName();
        this.handler.setProjectName(this.projectName);
    }

    public BuildTask(Project project,String vmLog,Task releaseTask) throws Exception {
        this.project = project;
        this.vmLog = vmLog;
        this.projectName = project.getFullName();
        this.handler.setProjectName(this.projectName);
        this.releaseTask = releaseTask;
    }

    public Project getProject() {
        return project;
    }

    public String getProjectName() {
        return projectName;
    }

    @Override
    public Object call() throws Exception {
        logger.info("构建线程开启,projectName="+this.projectName);
        if(!StringUtils.isEmpty(this.vmLog)){
            this.handler.addLogFile(this.vmLog);
        }
        BuildStatusEnum status = BuildStatusEnum.BUILD_FAILED;
        try {
            ProjectConfig projectConfig = this.project.getProjectConfig();
            List<JSONObject> dependency = projectConfig.getDependency();
            if(dependency.size() > 0){
                for (JSONObject object:dependency){
                    String isDeploy = object.getString("isDeploy");
                    String jarName = object.getString("jarName");
                    Project jarProject = new Project(jarName,true);
                    String logPath = jarProject.getBuildLogFilePath();
                    this.handler.addLogFile(logPath);
                    jarProject.setBuildHandler(this.handler);
                    jarProject.doBuild(isDeploy,this.projectName);
                    this.handler.saveMsgToFile("SUCCESS:工程"+jarName+"构建成功");
                    this.handler.removeLogFile(logPath);
                }
            }
            String logPath = this.project.getBuildLogFilePath();
            this.handler.addLogFile(logPath);
            this.project.setBuildHandler(this.handler);
            this.project.doBuild("",this.projectName);
            this.handler.saveMsgToFile("SUCCESS:工程"+this.projectName+"构建成功");
            this.handler.removeLogFile(logPath);
            status = BuildStatusEnum.BUILD_SUCCESS;

            //构建成功后发布
            if(this.releaseTask != null){
                this.doReleaseAfterBuild();
            }

        }catch (Exception e){
            logger.error("构建线程异常,projectName="+this.projectName,e);
            status = BuildStatusEnum.BUILD_FAILED;
            //异常时 保存异常信息至日志文件并发送ws消息
            this.handler.onMessage("ERROR:工程"+this.projectName+"构建失败。e:"+e.getMessage());
        }finally {
            this.taskClose();
            this.project.updateDependencyProjectStatus(status);
            this.project.updateBuildStatus(status,this.projectName);
        }
        return null;
    }

    /**
     * 构建成功后发布,使用 chainbasetask 方式
     */
    private void doReleaseAfterBuild(){
        TaskContainer taskContainer = TaskContainer.getInstance();
        taskContainer.addTask(this.releaseTask);
    }

    private void taskClose(){
        logger.info("构建线程关闭,projectName="+this.projectName);
        BuildTaskContainer.getInstance().removeTask(this.projectName);
    }
}
